<!-- components/custom-tabs/custom-tabs.vue -->
<script setup>
import { ref, onMounted, getCurrentInstance, computed } from 'vue'
// 接收组件外部传入的数据
const customTabsProps = defineProps({
  list: {
    type: Array,
    default: []
  }
})
// 自定义事件
const customTabsEmit = defineEmits(['click'])
// 初始默认第一个 tab 高亮
const tabIndex = ref(0)
// 记录节点信息，宽度和位置
const tabBarRect = ref([])
// 生命周期
onMounted(() => {
  // 在组件中应用，获取组件内部节点信息时需要调用 in 方法
  // 传入当页面实例，通过 getCurrentInstance 获取，相当于选项 API 中的 this
  const selectorQuery = uni.createSelectorQuery().in(getCurrentInstance())
  // 查找【所有节点】信息，用 selectAll 方法
  selectorQuery
    .selectAll('.custom-tabs, .tabbar-text')
    .boundingClientRect(([parent, ...data]) => {
      // 记录每个 tab 文字宽度和位置
      tabBarRect.value = data.map(({ width, left }) => {
        return { left: left - parent.left, width }
      })
    })
  // 执行节点查询
  selectorQuery.exec()
})
// 计算游标的位置
const cursorPosition = computed(() => {
  if (tabBarRect.value.length === 0) return
  const { width, left } = tabBarRect.value[tabIndex.value]
  return left + (width - 20) / 2
})
// 用户点击 tab
function onTabChange(index, tab) {
  // 显示/隐藏组件
  tabIndex.value = index
  // 触发自定义事件
  customTabsEmit('click', { index, ...tab })
}
</script>

<template>
  <view class="custom-tabs">
    <view
      v-for="(tab, index) in customTabsProps.list"
      :key="tab.label"
      @click="onTabChange(index, tab)"
      :class="{ active: tabIndex === index }"
      class="custom-tabs-bar"
    >
      <text class="tabbar-text">{{ tab.label }}</text>
    </view>
    <view
      class="custom-tabs-cursor"
      :style="{ left: cursorPosition + 'px' }"
    ></view>
  </view>
</template>

<style lang="scss">
// 自定义tabbar
.custom-tabs {
  display: flex;
  position: relative;
  padding: 0 30rpx;
}

.custom-tabs-bar {
  height: 80rpx;
  line-height: 80rpx;
  color: #979797;
  padding-right: 30rpx;
  position: relative;

  &.active {
    color: #121826;
    font-weight: 500;
  }
}

.tabbar-text {
  font-size: 30rpx;
}

.custom-tabs-cursor {
  position: absolute;
  bottom: 3px;
  left: 20px;

  width: 20px;
  height: 2px;
  border-radius: 2px;
  background-color: #2cb5a5;
  transition: all 0.3s ease-out;
}
</style>